﻿#pragma once
#ifndef CycleQueue_hpp
#define CycleQueue_hpp

#include<vector>
#include"Mutex.hpp"
#include"Lock.hpp"


namespace MMF{


template<typename T>
class CycleQueue
{

    std::vector<T> mDatas;  ///< 数据
    Mutex mMutex;           ///< 互斥量
    size_t mFront;          ///< 头
    size_t mTail;           ///< 尾

public:

    CycleQueue(size_t size)
        : mDatas(size)
        , mFront(0)
        , mTail(0)
    {
    }

    ~CycleQueue(){}

    bool Push(const T& val)
    {

        //上锁并写数据
        LockGuard lk(mMutex);
        mDatas[mFront] = val;
        mFront++;
        mFront = mFront % mDatas.size();

        return true;
    }

    bool Push(const T&& val)
    {
        //上锁并写数据
        LockGuard lk(mMutex);
        mDatas[mFront] = val;
        mFront++;
        mFront = mFront % mDatas.size();
        
        return true;
    }

    bool Pop(T& val)
    {
        LockGuard lk(mMutex);
        val = std::move(mDatas[mTail]);
        mTail++;
        mTail = mTail % mDatas.size();

        return true;
    }

    bool Back(T& val)
    {
        if (mDatas.size() == 0)
            return false;
            
        val = mDatas[mTail];
        return true;
    }

    bool Empty()
    {
        LockGuard lk(mMutex);
        return mTail == mFront;
    }

    size_t Size()
    {
        LockGuard lk(mMutex);
        return mDatas.size();
    }

    template<typename FuncT>
    void ForEach(const FuncT& func)
    {
        LockGuard lk(mMutex);
        size_t idx = mTail;
        while (idx != mFront)
        {
            func(mDatas[idx]);
            idx++;
            idx = idx % mDatas.size();
        }
    }

    size_t Count()
    {
        LockGuard lk(mMutex);
        return mDatas.size();
    }
};


}


#endif